Skip to content

Add Storybook test runner with a11y (axe) and CI workflow#36

Open
mrabbani wants to merge 4 commits into
mainfrom
chore/storybook-test-runner
Open

Add Storybook test runner with a11y (axe) and CI workflow#36
mrabbani wants to merge 4 commits into
mainfrom
chore/storybook-test-runner

Conversation

@mrabbani
Copy link
Copy Markdown
Member

@mrabbani mrabbani commented Feb 7, 2026

  • Add test-storybook and test-storybook:ci scripts
  • Add @storybook/test-runner and axe-playwright
  • Add .storybook/test-runner.ts for a11y checks (with a11y.disable opt-out)
  • Add GitHub Actions workflow to run UI tests on push (Playwright image)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automated UI testing for Storybook stories using Playwright with accessibility checks via axe
  • Documentation

    • Updated README and added comprehensive Storybook authoring guide
  • Chores

    • Added test automation npm scripts
    • Updated Storybook configuration and GitHub Actions workflows
    • Code formatting and configuration standardization across the project

Review Change Stack

mrabbani and others added 3 commits February 7, 2026 22:51
- Add test-storybook and test-storybook:ci scripts
- Add @storybook/test-runner and axe-playwright
- Add .storybook/test-runner.ts for a11y checks (with a11y.disable opt-out)
- Add GitHub Actions workflow to run UI tests on push (Playwright image)

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@arifulhoque7 arifulhoque7 force-pushed the chore/storybook-test-runner branch from bf5889b to 9998f68 Compare May 18, 2026 10:24
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

This PR establishes a complete Storybook testing and build infrastructure while normalizing formatting across the codebase. It adds accessibility testing via axe-playwright with a CI workflow, updates Storybook and webpack configuration for TypeScript support and CSS extraction, and reformats all story, component, provider, and configuration files with consistent line endings and whitespace.

Changes

Storybook Testing and Build Infrastructure

Layer / File(s) Summary
Storybook accessibility testing setup
.storybook/test-runner.ts, .github/workflows/test-ui.yml, package.json
New test-runner.ts configuration enables axe-playwright accessibility checks with context-aware skip support; CI workflow runs tests on push with Playwright container; npm scripts added for local and CI test execution.
Storybook and webpack build configuration
.storybook/main.ts, webpack.config.js
Storybook main.ts is updated with TypeScript typing and webpack customization for global React, PostCSS loader injection, and Babel transpilation; webpack.config.js explicitly configures entry, output paths, CSS extraction via MiniCssExtractPlugin, external dependencies, and module resolution with @/src alias.
Storybook preview and build utilities
.storybook/preview.js, postcss.config.js
Preview.js retains React global setup and ThemeProvider decorator while reformatted; postcss.config.js maintains Tailwind PostCSS plugin configuration.
Project configuration
tsconfig.json, .gitignore
TypeScript configuration is reformatted while preserving compiler options and path aliases; .gitignore updated to track package-lock.json and ignore config.bat.

Storybook Story Files Formatting

Layer / File(s) Summary
Alert and Avatar stories
src/components/ui/Alert.stories.tsx, src/components/ui/Avatar.stories.tsx
Story files reformatted with consistent line endings and whitespace while preserving all story metadata and JSX rendering.
Input-related stories
src/components/ui/Combobox.stories.tsx, src/components/ui/DropdownMenu.stories.tsx, src/components/ui/Input.stories.tsx, src/components/ui/InputGroup.stories.tsx, src/components/ui/InputOTP.stories.tsx
Story files reformatted while maintaining component usage, story exports, and JSX structure.
Progress and Slider stories
src/components/ui/Progress.stories.tsx, src/components/ui/Slider.stories.tsx
Story metadata and variants reformatted with no functional changes to story definitions.
Selection and Toggle stories
src/components/ui/SelectionType.stories.tsx, src/components/ui/Switch.stories.tsx, src/components/ui/ToggleGroup.stories.tsx, src/components/ui/Tooltip.stories.tsx
Story files reformatted while preserving story exports and rendering logic.
Textarea story
src/components/ui/Textarea.stories.tsx
Story file reformatted with no changes to story configuration or rendering.

UI Component Implementation Formatting

Layer / File(s) Summary
Dialog, Alert, and Badge components
src/components/ui/alert-dialog.tsx, src/components/ui/alert.tsx, src/components/ui/badge.tsx
Component implementations reformatted while preserving logic, props contracts, className composition, and exports.
Button, Card, and Combobox components
src/components/ui/button.tsx, src/components/ui/card.tsx, src/components/ui/combobox.tsx
Components reformatted while maintaining variant definitions, forwardRef typing, JSX structure, and wrapper logic.
Dropdown, Input, and Input group components
src/components/ui/dropdown-menu.tsx, src/components/ui/input.tsx, src/components/ui/input-group.tsx
Components reformatted while preserving Base UI wrapper structure, className logic, and exported subcomponents.
Modal, Notice, and Progress components
src/components/ui/modal.tsx, src/components/ui/notice.tsx, src/components/ui/progress.tsx
Components reformatted with formatting updates and added documentation comments while preserving portal logic, styling, and exports.
Select, Selection, and Slider components
src/components/ui/select.tsx, src/components/ui/selection-type.tsx, src/components/ui/slider.tsx
Components reformatted while maintaining variant configurations, context behavior, and wrapper logic.
Switch, Textarea, Toggle, and Tooltip components
src/components/ui/switch.tsx, src/components/ui/textarea.tsx, src/components/ui/toggle-group.tsx, src/components/ui/tooltip.tsx
Components reformatted with consistent line endings while preserving props handling, event logic, and exports.
UI component barrel export
src/components/ui/index.ts
Re-export list reorganized with consistent formatting while preserving all exported component symbols and types.

Theme Provider and Export System Formatting

Layer / File(s) Summary
Theme provider implementation
src/providers/theme-provider.tsx
Provider implementation reformatted across all sections (imports, types, helpers, component logic, hooks) while preserving theme token management, CSS variable generation, context-based switching, and all exported hooks.
Root exports and utilities
src/index.ts, src/lib/utils.ts
Export statements reorganized for consistency while preserving all exported providers, components, types, themes, and utilities; utils.ts maintains cn utility function with clsx and tailwind-merge.
Theme tokens and stylesheet
src/themes/index.ts, src/styles.css
Theme token constants and helper functions preserved with formatting updates; stylesheet regenerated with identical theme variables, Tailwind mappings, scoped base/component styles, and animations.

Documentation and Workflows

Layer / File(s) Summary
Documentation updates
README.md, docs/STORYBOOK.md
README reformatted with consistent presentation while maintaining coverage of installation, development, styling, components, themes, and configuration; new STORYBOOK.md guide added with story templates, component examples, argTypes guidance, testing setup, and repo-specific recommendations.
Storybook deployment workflow
.github/workflows/deploy-storybook.yml
GitHub Pages deployment workflow reformatted with no changes to pipeline logic, action versions, or deployment configuration.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • getdokan/plugin-ui#61: Updates Card UI component formatting in the same way as this PR's component refactoring pass.

🐰 A tale of test automation, webpack spins,
With Storybook's axe that accessibility wins,
Formatted neat from core to seam,
A testing dream and build-time scheme!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and accurately summarizes the main changes: adding a Storybook test runner with accessibility checks (axe) and a CI workflow for automated UI testing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/storybook-test-runner

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
src/components/ui/slider.tsx (1)

27-41: 💤 Low value

Consider removing commented-out code.

The commented trackClass function spans 15 lines. If this code is no longer needed, removing it would improve readability. If it might be needed in the future, consider documenting why it's preserved in a TODO comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/slider.tsx` around lines 27 - 41, Remove the large
commented-out block for the trackClass helper in src/components/ui/slider.tsx
(the commented function named trackClass); either delete it entirely to improve
readability or, if you want to keep it, replace the block with a one-line TODO
comment explaining why it’s preserved and where an equivalent implementation
lives, referencing trackClass so reviewers can locate the intent quickly.
.github/workflows/test-ui.yml (1)

19-20: ⚡ Quick win

Use npm ci for reproducible CI installs.

Line 20 should use lockfile-based install to avoid dependency drift between runs.

Proposed change
-      - name: Install dependencies
-        run: npm install
+      - name: Install dependencies
+        run: npm ci
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test-ui.yml around lines 19 - 20, The CI workflow step
named "Install dependencies" currently runs npm install which can produce
non-reproducible installs; change that step to run npm ci to perform a
lockfile-based, deterministic install (and optionally ensure package-lock.json
or npm-shrinkwrap.json is committed). Update the step that executes the install
command (the "Install dependencies" job/step) to use npm ci instead of npm
install, and add a brief check or comment to fail early if no lockfile is
present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/STORYBOOK.md`:
- Line 271: The doc references the preview config with two different filenames
causing confusion; open STORYBOOK.md and standardize all mentions to the actual
preview filename used in the repo (replace `.storybook/preview.js` occurrences
with `.storybook/preview.tsx` if the project uses TypeScript, or vice versa if
the real file is `.storybook/preview.js`), ensuring the references at the
currently mismatched spots (the lines referencing `.storybook/preview.tsx` and
the later `.storybook/preview.js`) are updated so every mention uses the single
correct filename.

In `@package.json`:
- Line 51: The package.json script "test-storybook:ci" uses CLI tools that
aren't declared as devDependencies; add the missing devDependencies for
"concurrently", "wait-on", and "http-server" (as devDependencies) so CI installs
them on fresh installs and the "test-storybook:ci" script can run; update
package.json's devDependencies section accordingly and run npm/yarn install to
verify.

In `@src/components/ui/index.ts`:
- Around line 64-69: Update the inconsistent quote and semicolon style in the UI
barrel exports: change the single quotes to double quotes and add trailing
semicolons for the exports that use single quotes currently — specifically the
export lines that include Toggle, ToggleGroup, ToggleGroupItem, Tabs, TabsList,
TabsTrigger, TabsContent, tabsListVariants, SelectionType, SelectionItem, and
selectionItemVariants — so all export statements match the double-quote +
semicolon style used elsewhere in this file.

In `@src/providers/theme-provider.tsx`:
- Around line 470-473: Replace the template-string class concatenation for the
component's root element with the shared cn() utility: when setting className
use cn(...) to merge "pui-root", the conditional dark class (based on
resolvedMode === "dark"), and the incoming className prop; update the line that
currently constructs className with `` `pui-root ${resolvedMode === "dark" ?
"dark" : ""} ${className}`.trim()`` to call cn("pui-root", resolvedMode ===
"dark" && "dark", className) so class merging follows the project's
cn/clsx+tw-merge convention.

In `@src/themes/index.ts`:
- Around line 6-125: The theme tokens in this file (e.g., defaultTheme,
defaultDarkTheme, dokanTheme, dokanDarkTheme, blueTheme, blueDarkTheme,
greenTheme, greenDarkTheme, amberTheme, amberDarkTheme, slateTheme,
slateDarkTheme) use "oklch(...)" strings but must be converted to the HSL
raw-value contract (plain "H S% L%" channel strings without the hsl() wrapper).
Update every color token (primary, primaryForeground, ring, background,
foreground, card, cardForeground, secondary, secondaryForeground, muted,
mutedForeground, border, input, etc.) to their equivalent HSL raw channel
strings (leave radius values untouched), ensuring all dark theme spreads
(...defaultDarkTheme) also receive converted HSL values.

In `@webpack.config.js`:
- Around line 19-28: The externals block currently replaces
defaultConfig.externals, removing `@wordpress/scripts` defaults; change it to
merge with defaults by using the existing defaultConfig.externals and spreading
it (e.g., create externals = { ...defaultConfig.externals, react: 'react',
'react-dom': 'react-dom', '`@wordpress/element`': '`@wordpress/element`',
'`@wordpress/components`': '`@wordpress/components`', '`@wordpress/block-editor`':
'`@wordpress/block-editor`', '`@wordpress/hooks`': '`@wordpress/hooks`',
'`@wordpress/i18n`': '`@wordpress/i18n`', quill: 'quill' }) so you preserve defaults
while adding your custom entries; update the webpack config where externals is
set (referencing defaultConfig and the externals property) to apply this merged
object.

---

Nitpick comments:
In @.github/workflows/test-ui.yml:
- Around line 19-20: The CI workflow step named "Install dependencies" currently
runs npm install which can produce non-reproducible installs; change that step
to run npm ci to perform a lockfile-based, deterministic install (and optionally
ensure package-lock.json or npm-shrinkwrap.json is committed). Update the step
that executes the install command (the "Install dependencies" job/step) to use
npm ci instead of npm install, and add a brief check or comment to fail early if
no lockfile is present.

In `@src/components/ui/slider.tsx`:
- Around line 27-41: Remove the large commented-out block for the trackClass
helper in src/components/ui/slider.tsx (the commented function named
trackClass); either delete it entirely to improve readability or, if you want to
keep it, replace the block with a one-line TODO comment explaining why it’s
preserved and where an equivalent implementation lives, referencing trackClass
so reviewers can locate the intent quickly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 934228da-a3b7-4987-9176-35e967e76725

📥 Commits

Reviewing files that changed from the base of the PR and between 03e7989 and 48ac44e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (51)
  • .github/workflows/deploy-storybook.yml
  • .github/workflows/test-ui.yml
  • .gitignore
  • .storybook/main.ts
  • .storybook/preview.js
  • .storybook/test-runner.ts
  • README.md
  • docs/STORYBOOK.md
  • package.json
  • postcss.config.js
  • src/components/ui/Alert.stories.tsx
  • src/components/ui/Avatar.stories.tsx
  • src/components/ui/Combobox.stories.tsx
  • src/components/ui/DropdownMenu.stories.tsx
  • src/components/ui/Input.stories.tsx
  • src/components/ui/InputGroup.stories.tsx
  • src/components/ui/InputOTP.stories.tsx
  • src/components/ui/Progress.stories.tsx
  • src/components/ui/SelectionType.stories.tsx
  • src/components/ui/Slider.stories.tsx
  • src/components/ui/Switch.stories.tsx
  • src/components/ui/Textarea.stories.tsx
  • src/components/ui/ToggleGroup.stories.tsx
  • src/components/ui/Tooltip.stories.tsx
  • src/components/ui/alert-dialog.tsx
  • src/components/ui/alert.tsx
  • src/components/ui/badge.tsx
  • src/components/ui/button.tsx
  • src/components/ui/card.tsx
  • src/components/ui/combobox.tsx
  • src/components/ui/dropdown-menu.tsx
  • src/components/ui/index.ts
  • src/components/ui/input-group.tsx
  • src/components/ui/input.tsx
  • src/components/ui/modal.tsx
  • src/components/ui/notice.tsx
  • src/components/ui/progress.tsx
  • src/components/ui/select.tsx
  • src/components/ui/selection-type.tsx
  • src/components/ui/slider.tsx
  • src/components/ui/switch.tsx
  • src/components/ui/textarea.tsx
  • src/components/ui/toggle-group.tsx
  • src/components/ui/tooltip.tsx
  • src/index.ts
  • src/lib/utils.ts
  • src/providers/theme-provider.tsx
  • src/styles.css
  • src/themes/index.ts
  • tsconfig.json
  • webpack.config.js

Comment thread docs/STORYBOOK.md
## 5. Decorators (global theme / layout)
All stories run inside the preview decorators (see `.storybook/preview.tsx`), which:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix inconsistent preview config filename references.

Line 271/383 point to .storybook/preview.tsx, but this doc later references .storybook/preview.js (Line 369). Please standardize these references to the actual file to avoid broken guidance.

Also applies to: 383-383

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/STORYBOOK.md` at line 271, The doc references the preview config with
two different filenames causing confusion; open STORYBOOK.md and standardize all
mentions to the actual preview filename used in the repo (replace
`.storybook/preview.js` occurrences with `.storybook/preview.tsx` if the project
uses TypeScript, or vice versa if the real file is `.storybook/preview.js`),
ensuring the references at the currently mismatched spots (the lines referencing
`.storybook/preview.tsx` and the later `.storybook/preview.js`) are updated so
every mention uses the single correct filename.

Comment thread package.json
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"test-storybook": "test-storybook",
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"npm run build-storybook && npx http-server storybook-static --port 6006 --silent\" \"wait-on tcp:6006 && test-storybook\"",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether required CLI deps for test-storybook:ci are declared.
rg -n '"test-storybook:ci"' package.json
rg -n '"(concurrently|wait-on|http-server)"' package.json

Repository: getdokan/plugin-ui

Length of output: 282


🏁 Script executed:

cat -n package.json

Repository: getdokan/plugin-ui

Length of output: 4526


test-storybook:ci script depends on CLIs not declared in devDependencies.

Line 51's test-storybook:ci script invokes concurrently, wait-on, and http-server, but none of these packages are present in devDependencies. This will cause CI to fail on fresh installs.

Add the missing dependencies:

Proposed change
   "devDependencies": {
+    "concurrently": "^9.0.1",
+    "wait-on": "^8.0.1",
+    "http-server": "^14.1.1",
     "`@babel/preset-react`": "^7.26.0",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"npm run build-storybook && npx http-server storybook-static --port 6006 --silent\" \"wait-on tcp:6006 && test-storybook\"",
"devDependencies": {
"concurrently": "^9.0.1",
"wait-on": "^8.0.1",
"http-server": "^14.1.1",
"`@babel/preset-react`": "^7.26.0",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 51, The package.json script "test-storybook:ci" uses
CLI tools that aren't declared as devDependencies; add the missing
devDependencies for "concurrently", "wait-on", and "http-server" (as
devDependencies) so CI installs them on fresh installs and the
"test-storybook:ci" script can run; update package.json's devDependencies
section accordingly and run npm/yarn install to verify.

Comment on lines +64 to +69
export { Toggle } from './toggle'
export { ToggleGroup, ToggleGroupItem } from './toggle-group'
export { Progress, ProgressTrack, ProgressIndicator, ProgressLabel, ProgressValue, CircularProgress, type ProgressProps, type CircularProgressProps } from "./progress";
export { Slider, type SliderProps } from "./slider";
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants } from './tabs'
export { SelectionType, SelectionItem, selectionItemVariants } from './selection-type'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Run ESLint on the index.ts file to check for quote-style violations

npm run lint -- src/components/ui/index.ts

Repository: getdokan/plugin-ui

Length of output: 195


🏁 Script executed:

# Check for ESLint configuration and the actual file content
find . -maxdepth 2 -type f \( -name ".eslintrc*" -o -name "eslint.config.*" \) | head -20

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

# Check the actual content of the file to verify quote styles
cat -n src/components/ui/index.ts | tail -20

Repository: getdokan/plugin-ui

Length of output: 1157


🏁 Script executed:

# Check package.json to understand npm scripts and dependencies
cat package.json | grep -A 10 '"lint"'

Repository: getdokan/plugin-ui

Length of output: 395


🏁 Script executed:

# Search more thoroughly for ESLint config
find . -type f -name ".eslintrc*" -o -name "eslint.config.*" 2>/dev/null | head -20

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

# Check if there's an eslint config in package.json itself
cat package.json | grep -A 20 '"eslintConfig"'

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

# Try to find all config files in root
ls -la | grep -E '^\.'

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

# List all files in repository root
ls -la | head -30

Repository: getdokan/plugin-ui

Length of output: 1078


🏁 Script executed:

# Search for any file containing eslint configuration
find . -maxdepth 3 -type f \( -name "*config*" -o -name "*.json" \) | grep -v node_modules | head -20

Repository: getdokan/plugin-ui

Length of output: 204


🏁 Script executed:

# Check if eslint is in package.json dependencies
cat package.json | grep -i eslint

Repository: getdokan/plugin-ui

Length of output: 108


🏁 Script executed:

# Check for .eslintignore and other hidden eslint files
ls -la | grep eslint

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

# Search for any eslint references in the codebase
rg "eslint" --type json --type javascript --type typescript | head -20

Repository: getdokan/plugin-ui

Length of output: 97


🏁 Script executed:

# Check .github directory for CI/CD config that might have eslint setup
find .github -type f -name "*.yml" -o -name "*.yaml" | xargs cat 2>/dev/null

Repository: getdokan/plugin-ui

Length of output: 2018


Fix quote style inconsistency.

Lines 64-65 and 68-69 use single quotes while the rest of the file uses double quotes. This inconsistency also appears with semicolons (missing on those same lines). Update to use consistent double quotes and semicolons throughout, matching the rest of the file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/index.ts` around lines 64 - 69, Update the inconsistent
quote and semicolon style in the UI barrel exports: change the single quotes to
double quotes and add trailing semicolons for the exports that use single quotes
currently — specifically the export lines that include Toggle, ToggleGroup,
ToggleGroupItem, Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants,
SelectionType, SelectionItem, and selectionItemVariants — so all export
statements match the double-quote + semicolon style used elsewhere in this file.

Comment on lines +470 to +473
className={`pui-root ${
resolvedMode === "dark" ? "dark" : ""
} ${className}`.trim()}
style={{ ...cssVariables, ...style }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use cn() for class merging instead of template-string concatenation.

Line 470–Line 473 should use the shared merge utility for consistency and safer class composition.

Proposed change
 import React, {
   createContext,
   useCallback,
   useContext,
   useEffect,
   useMemo,
   useState,
   type ReactNode,
 } from "react";
+import { cn } from "`@/lib/utils`";
@@
         data-pui-plugin={pluginId}
         data-pui-mode={resolvedMode}
-        className={`pui-root ${
-          resolvedMode === "dark" ? "dark" : ""
-        } ${className}`.trim()}
+        className={cn("pui-root", resolvedMode === "dark" && "dark", className)}
         style={{ ...cssVariables, ...style }}
       >

As per coding guidelines, "Use the cn() utility function to merge Tailwind CSS classes (combines clsx + tailwind-merge)".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className={`pui-root ${
resolvedMode === "dark" ? "dark" : ""
} ${className}`.trim()}
style={{ ...cssVariables, ...style }}
className={cn("pui-root", resolvedMode === "dark" && "dark", className)}
style={{ ...cssVariables, ...style }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/theme-provider.tsx` around lines 470 - 473, Replace the
template-string class concatenation for the component's root element with the
shared cn() utility: when setting className use cn(...) to merge "pui-root", the
conditional dark class (based on resolvedMode === "dark"), and the incoming
className prop; update the line that currently constructs className with ``
`pui-root ${resolvedMode === "dark" ? "dark" : ""} ${className}`.trim()`` to
call cn("pui-root", resolvedMode === "dark" && "dark", className) so class
merging follows the project's cn/clsx+tw-merge convention.

Comment thread src/themes/index.ts
Comment on lines +6 to +125
export const defaultTheme: ThemeTokens = {
primary: "oklch(0.5410 0.2120 265.7540)",
primaryForeground: "oklch(1.0000 0 0)",
ring: "oklch(0.5410 0.2120 265.7540)",
radius: "0.5rem",
};
/**
* Default dark theme tokens
*/
export const defaultDarkTheme: ThemeTokens = {
background: "oklch(0.1450 0.0140 285.7500)",
foreground: "oklch(0.9850 0.0030 264.5000)",
card: "oklch(0.1450 0.0140 285.7500)",
cardForeground: "oklch(0.9850 0.0030 264.5000)",
primary: "oklch(0.6230 0.2000 265.7540)",
primaryForeground: "oklch(0.1450 0.0140 285.7500)",
secondary: "oklch(0.2690 0.0150 264.5419)",
secondaryForeground: "oklch(0.9850 0.0030 264.5000)",
muted: "oklch(0.2690 0.0150 264.5419)",
mutedForeground: "oklch(0.7110 0.0200 264.3637)",
border: "oklch(0.3690 0.0150 264.5313)",
input: "oklch(0.3690 0.0150 264.5313)",
ring: "oklch(0.6230 0.2000 265.7540)",
};
/**
* Dokan theme - Purple brand
*/
export const dokanTheme: ThemeTokens = {
primary: "oklch(0.5410 0.2120 265.7540)", // #7047EB
primaryForeground: "oklch(1.0000 0 0)",
ring: "oklch(0.5410 0.2120 265.7540)",
radius: "0.375rem",
};
/**
* Dokan dark theme
*/
export const dokanDarkTheme: ThemeTokens = {
...defaultDarkTheme,
primary: "oklch(0.6230 0.2000 265.7540)",
ring: "oklch(0.6230 0.2000 265.7540)",
};
/**
* Blue theme - For plugins like WeMail
*/
export const blueTheme: ThemeTokens = {
primary: "oklch(0.6230 0.2140 255.0900)", // Blue
primaryForeground: "oklch(1.0000 0 0)",
ring: "oklch(0.6230 0.2140 255.0900)",
radius: "0.5rem",
};
/**
* Blue dark theme
*/
export const blueDarkTheme: ThemeTokens = {
...defaultDarkTheme,
primary: "oklch(0.7000 0.1800 255.0900)",
ring: "oklch(0.7000 0.1800 255.0900)",
};
/**
* Green theme - For plugins with nature/growth branding
*/
export const greenTheme: ThemeTokens = {
primary: "oklch(0.6470 0.1780 145.0000)", // Green
primaryForeground: "oklch(1.0000 0 0)",
ring: "oklch(0.6470 0.1780 145.0000)",
radius: "0.5rem",
};
/**
* Green dark theme
*/
export const greenDarkTheme: ThemeTokens = {
...defaultDarkTheme,
primary: "oklch(0.7200 0.1600 145.0000)",
ring: "oklch(0.7200 0.1600 145.0000)",
};
/**
* Orange/Amber theme - For warm branding
*/
export const amberTheme: ThemeTokens = {
primary: "oklch(0.7690 0.1880 70.0800)", // Amber/Orange
primaryForeground: "oklch(0.2100 0.0340 32.0000)",
ring: "oklch(0.7690 0.1880 70.0800)",
radius: "0.5rem",
};
/**
* Amber dark theme
*/
export const amberDarkTheme: ThemeTokens = {
...defaultDarkTheme,
primary: "oklch(0.8200 0.1600 70.0800)",
ring: "oklch(0.8200 0.1600 70.0800)",
};
/**
* Slate/Neutral theme - For minimal, professional look
*/
export const slateTheme: ThemeTokens = {
primary: "oklch(0.3050 0.0170 264.5419)", // Slate
primaryForeground: "oklch(1.0000 0 0)",
ring: "oklch(0.3050 0.0170 264.5419)",
radius: "0.375rem",
};
/**
* Slate dark theme
*/
export const slateDarkTheme: ThemeTokens = {
...defaultDarkTheme,
primary: "oklch(0.7110 0.0200 264.3637)",
ring: "oklch(0.7110 0.0200 264.3637)",
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Theme token format is inconsistent with the required HSL raw-value contract.

Line 6 onward defines ThemeTokens with oklch(...) values; this should be migrated to raw HSL channel strings (without hsl() wrapper) to match the theme-system contract.

As per coding guidelines, "Theme system should use HSL values without the hsl() wrapper (e.g., '220 90% 56%') for all ThemeTokens".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/themes/index.ts` around lines 6 - 125, The theme tokens in this file
(e.g., defaultTheme, defaultDarkTheme, dokanTheme, dokanDarkTheme, blueTheme,
blueDarkTheme, greenTheme, greenDarkTheme, amberTheme, amberDarkTheme,
slateTheme, slateDarkTheme) use "oklch(...)" strings but must be converted to
the HSL raw-value contract (plain "H S% L%" channel strings without the hsl()
wrapper). Update every color token (primary, primaryForeground, ring,
background, foreground, card, cardForeground, secondary, secondaryForeground,
muted, mutedForeground, border, input, etc.) to their equivalent HSL raw channel
strings (leave radius values untouched), ensuring all dark theme spreads
(...defaultDarkTheme) also receive converted HSL values.

Comment thread webpack.config.js
Comment on lines +19 to +28
externals: {
react: 'react',
'react-dom': 'react-dom',
'@wordpress/element': '@wordpress/element',
'@wordpress/components': '@wordpress/components',
'@wordpress/block-editor': '@wordpress/block-editor',
'@wordpress/hooks': '@wordpress/hooks',
'@wordpress/i18n': '@wordpress/i18n',
quill: 'quill',
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current config overrides externals instead of merging defaults.
rg -n "externals\\s*:" webpack.config.js -n -A12 -B2
rg -n "defaultConfig\\.externals" webpack.config.js

Repository: getdokan/plugin-ui

Length of output: 586


🏁 Script executed:

rg -n "defaultConfig" webpack.config.js -B5 -A5

Repository: getdokan/plugin-ui

Length of output: 1714


🏁 Script executed:

rg -n "from.*`@wordpress/scripts`\|import.*defaultConfig" .

Repository: getdokan/plugin-ui

Length of output: 44


🏁 Script executed:

fd webpack.config.js -x cat -n {} \; | head -40

Repository: getdokan/plugin-ui

Length of output: 1640


🌐 Web query:

@wordpress/scripts webpack config externals defaults

💡 Result:

The @wordpress/scripts package provides a default Webpack configuration that automatically handles the externalization of WordPress core packages (e.g., @wordpress/components, @wordpress/element) [1][2]. This is primarily managed by the @wordpress/dependency-extraction-webpack-plugin, which is included in the default configuration [1]. Key points regarding externals and customization: 1. Default Behavior: The default configuration automatically maps WordPress package imports to their corresponding global variables (e.g., @wordpress/blob becomes wp.blob) [1]. This allows you to use import statements in your code without bundling the entire WordPress core library, ensuring your scripts rely on the versions already loaded by WordPress [1][3]. 2. Customizing Externals: If you need to modify or extend the default externals, you can create a webpack.config.js file in your project root [4][5]. You can import the default configuration and merge your changes [4][5]. 3. Conflicts with DependencyExtractionWebpackPlugin: The default plugin overlaps with standard Webpack externals [1]. If you add custom externals that conflict with the plugin's automatic extraction, you may need to remove the default instance of the DependencyExtractionWebpackPlugin from the plugins array and re-add it with custom options, or use the externals option directly if you do not need the automatic dependency list generation [1]. 4. Disabling Externals: If you are building a standalone application that does not run within the WordPress environment, you can invoke the build or start scripts with the --webpack-no-externals flag to prevent the automatic externalization of WordPress packages [6]. To extend the configuration, use the following pattern in your webpack.config.js: const defaultConfig = require( '@wordpress/scripts/config/webpack.config'); module.exports = {...defaultConfig, // Add your custom externals or overrides here externals: {...defaultConfig.externals, 'my-custom-library': 'MyGlobalVar', }, }; Always ensure you are pinning your @wordpress/scripts version, as major updates may restructure the internal configuration [4].

Citations:


Do not replace defaultConfig.externals; merge it instead.

Line 19 replaces the entire externals map, which removes defaults from @wordpress/scripts. The correct pattern is to spread the defaults and add custom externals:

-    externals: {
+    externals: {
+        ...defaultConfig.externals,
         react: 'react',
         'react-dom': 'react-dom',
         '`@wordpress/element`': '`@wordpress/element`',

This aligns with the pattern used for other config properties (output, module, plugins, resolve) and matches the official @wordpress/scripts documentation for extending configurations.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
externals: {
react: 'react',
'react-dom': 'react-dom',
'@wordpress/element': '@wordpress/element',
'@wordpress/components': '@wordpress/components',
'@wordpress/block-editor': '@wordpress/block-editor',
'@wordpress/hooks': '@wordpress/hooks',
'@wordpress/i18n': '@wordpress/i18n',
quill: 'quill',
},
externals: {
...defaultConfig.externals,
react: 'react',
'react-dom': 'react-dom',
'`@wordpress/element`': '`@wordpress/element`',
'`@wordpress/components`': '`@wordpress/components`',
'`@wordpress/block-editor`': '`@wordpress/block-editor`',
'`@wordpress/hooks`': '`@wordpress/hooks`',
'`@wordpress/i18n`': '`@wordpress/i18n`',
quill: 'quill',
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webpack.config.js` around lines 19 - 28, The externals block currently
replaces defaultConfig.externals, removing `@wordpress/scripts` defaults; change
it to merge with defaults by using the existing defaultConfig.externals and
spreading it (e.g., create externals = { ...defaultConfig.externals, react:
'react', 'react-dom': 'react-dom', '`@wordpress/element`': '`@wordpress/element`',
'`@wordpress/components`': '`@wordpress/components`', '`@wordpress/block-editor`':
'`@wordpress/block-editor`', '`@wordpress/hooks`': '`@wordpress/hooks`',
'`@wordpress/i18n`': '`@wordpress/i18n`', quill: 'quill' }) so you preserve defaults
while adding your custom entries; update the webpack config where externals is
set (referencing defaultConfig and the externals property) to apply this merged
object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants